﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GTA
{
    static class Program
    {
        #region Application Context Objects
        public static BusinessEntity.Configuration.SystemConfiguration SystemConfiguration = null;
        public static BusinessEntity.Configuration.Holidays Holidays = null;
        public static List<BusinessEntity.Project> Projects = null;
        public static BusinessEntity.UserManagement.User LoggedUser;
        #endregion

        #region Stating System
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            if (!IsRunning())
            {
                try
                {
                    while (StartSystem()) ;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ocorreu um erro durante a inicialização do sistema.\r\nDetalhes: " + GTA.Common.Util.GetFullException(ex), "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        private static bool StartSystem()
        {
            FrmLogin frmLogin = new FrmLogin();
            Application.Run(frmLogin);
            FrmMain frmMain = null;
            if (Convert.ToBoolean(frmLogin.Tag))
            {
                bool passwordChanged = true;
                BusinessLogic.GTA bl = new BusinessLogic.GTA();
                if (bl.CheckUserFirstAccess(Program.LoggedUser.ID))
                    passwordChanged = HandleUserFirstAccess();

                if (passwordChanged)
                {
                    FrmSplash frmSplash = new FrmSplash();
                    Application.Run(frmSplash);
                    if (Convert.ToBoolean(frmSplash.Tag))
                    {
                        frmMain = new FrmMain();
                        Application.Run(frmMain);
                    }
                }
            }
            return frmMain != null && frmMain.Tag != null ? Convert.ToBoolean(frmMain.Tag) : false;
        }
        private static bool HandleUserFirstAccess()
        {
            bool handled = false;
            FrmChangePassword frmChange = new FrmChangePassword();
            Application.Run(frmChange);
            if (frmChange.Tag != null && Convert.ToBoolean(frmChange.Tag))
            {
                BusinessLogic.GTA bl = new BusinessLogic.GTA();
                bl.UpdateUserFirstAccess(Program.LoggedUser.ID, true);
                handled = true;
            }
            return handled;
        }
        private static bool IsRunning()
        {
            bool result = false;
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("GTA");
            if (processes != null && processes.Length > 1)
            {
                result = true;
                foreach (System.Diagnostics.Process proc in processes)
                {
                    bool p = SetForegroundWindow(proc.MainWindowHandle);
                    if (p)
                        SetFocus(new HandleRef(null, proc.MainWindowHandle));
                }
            }
            return result;
        }
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr SetFocus(HandleRef hWnd);
        #endregion

        #region Methods
        public static void LoadSystemConfiguration()
        {
            BusinessLogic.Configuration config = new GTA.BusinessLogic.Configuration();
            Program.SystemConfiguration = config.GetSystemConfiguration(LoggedUser);
            Program.Holidays = config.GetHolidays();
        }
        internal static void SaveSystemConfiguration()
        {
            new GTA.BusinessLogic.Configuration().SaveSystemConfiguration(Program.SystemConfiguration, LoggedUser);
        }
        public static void StartTeamSystemInstance()
        {
            BusinessLogic.GTA bl = new BusinessLogic.GTA();
            bl.StartTeamSystemInstance();
        }
        public static void LoadProjects()
        {
            BusinessLogic.GTA bl = new BusinessLogic.GTA();
            Program.Projects = bl.ListTeamProjects();
        }
        public static void UpdateLoggedUserProjects()
        {
            if (Program.Projects != null &&
                Program.Projects.Count > 0 &&
                Program.LoggedUser != null &&
                Program.LoggedUser.UserProjects != null &&
                Program.LoggedUser.UserProjects.Count > 0)
                Program.LoggedUser.UserProjects.RemoveAll(it => !Program.Projects.Exists(itp => itp.Name.CompareTo(it.Name) == 0));
        }
        public static bool CheckOpenedWindow<T>(bool makeFocus)
            where T : Form
        {
            bool found = false;
            T form = GetForm<T>();
            if (form != null)
            {
                found = true;
                if (makeFocus)
                    SetWindowFocus(form);
            }
            return found;
        }
        public static T GetForm<T>()
            where T : Form
        {
            T form = default(T);
            foreach (Form itemForm in Application.OpenForms)
            {
                if (itemForm is T)
                {
                    form = (T)(Object)itemForm;
                    break;
                }
            }
            return form;
        }
        private static void SetWindowFocus(Form wd)
        {
            if (wd != null)
            {
                if (wd.InvokeRequired)
                    wd.Invoke(new Action<Form>(SetWindowFocus), new object[] { wd });
                else
                    wd.Focus();
            }
        }
        #endregion
    }
}
